package popup

import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.PopupWindow
import android.widget.TextView
import app.AppContext
import com.hontech.pizzav2.R
import db.Cargo
import db.Order
import event.DeliveryTaskEvent
import event.StatusChangedEvent
import event.motor.DeliveryChangedEvent
import ext.AppTimer
import ext.log
import manager.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import task.DeliveryTask
import task.OrderSaveTask
import task.debug.PostLogTask
import view.DeliveryView
import view.LoadImageView
import view.ProgressBarView.Step
import view.StepView

class DeliveryWindow {

    companion object {
        val Instance: DeliveryWindow by lazy { DeliveryWindow() }
        const val TAK_TIME = 45f
        const val DELIVER_TIME = 30f
        const val PREHEAT_TIME = 300f
        var isShow = false
    }

    private var cargo: Cargo? = null
    private var take = 0
    private val view = LayoutInflater.from(AppContext).inflate(R.layout.popup_delivery, null)
    private val iconImageView = view.findViewById<LoadImageView>(R.id.id_delivery_image_view)
    private val deliveryView = view.findViewById<DeliveryView>(R.id.id_delivery_deliver_view)
    private val stepView = view.findViewById<StepView>(R.id.id_delivery_step_view)
    private val window = PopupWindow(
        view, WindowManager.LayoutParams.MATCH_PARENT,
        WindowManager.LayoutParams.MATCH_PARENT, true
    )
    private val textView = view.findViewById<TextView>(R.id.id_delivery_temp_text_view)

    private val deliveryTimer = AppTimer { onDeliveryTimeout() }
    private val closeTimer = AppTimer { dismiss() }
    private var deliveryFlag: Boolean? = null

    init {
        window.animationStyle = R.style.PayTheme
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onDeliveryTaskEvent(env: DeliveryTaskEvent) {
        log("发送出货命令:${env.cargo}")
        cargo = env.cargo
        if (cargo == null) {
            onError()
            return
        }
    }

    //    const val Take1 = 0x90 // 取货 + 预热 + 加热 + 出货
    //    const val Take2 = 0x8F // 取货 + 加热 + 出货
    //    const val Take3 = 0x91 // 取货 + 出货
    private fun take1(step: Int = 0) {
        val info = WaresManager.selectInfo()
        val time =
            (if (info.wares.waveHeatTime > info.wares.infraredHeatTime)
                info.wares.waveHeatTime
            else
                info.wares.infraredHeatTime).toFloat()
        deliveryView.progress.steps = arrayOf(
            Step("Taking", TAK_TIME),
            Step("Preheating", PREHEAT_TIME), Step("Heating", time),
            Step("Delivering", DELIVER_TIME)
        )
        when (step) {
            DeliveryChangedEvent.Preheat -> {
                deliveryView.progress.start(TAK_TIME)
            }

            DeliveryChangedEvent.Heat -> {
                deliveryView.progress.start(TAK_TIME + PREHEAT_TIME)
            }

            DeliveryChangedEvent.Deliver -> {
                deliveryView.progress.start(TAK_TIME + PREHEAT_TIME + time)
            }

            DeliveryChangedEvent.Success -> {
                deliveryView.progress.start(TAK_TIME + PREHEAT_TIME + time + DELIVER_TIME)
            }

            0 -> deliveryView.progress.start()
        }
    }

    private fun take2(step: Int = 0) {
        val info = WaresManager.selectInfo()
        val time =
            (if (info.wares.waveHeatTime > info.wares.infraredHeatTime)
                info.wares.waveHeatTime
            else info.wares.infraredHeatTime).toFloat()
        deliveryView.progress.steps = arrayOf(
            Step("Taking", TAK_TIME), Step("Heating", time),
            Step("Delivering", DELIVER_TIME)
        )
        when (step) {
            0 -> deliveryView.progress.start()

            DeliveryChangedEvent.Heat -> {
                deliveryView.progress.start(TAK_TIME)
            }
            DeliveryChangedEvent.Deliver -> {
                deliveryView.progress.start(TAK_TIME + time)
            }
            DeliveryChangedEvent.Success -> {
                deliveryView.progress.start(TAK_TIME + time + DELIVER_TIME)
            }
        }
    }

    private fun take3(step: Int = 0) {
        val info = WaresManager.selectInfo()
        deliveryView.progress.steps = arrayOf(
            Step("Taking", TAK_TIME),
            Step("Delivering", DELIVER_TIME - info.wares.heatDissipationTime)
        )
        when (step) {
            0 -> deliveryView.progress.start()

            DeliveryChangedEvent.Deliver -> {
                deliveryView.progress.start(TAK_TIME)
            }

            DeliveryChangedEvent.Success -> {
                deliveryView.progress.start(TAK_TIME + DELIVER_TIME - info.wares.heatDissipationTime)
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onStatusChanged(env: StatusChangedEvent) {
        if (textView.visibility != View.VISIBLE) {
            return
        }
        val tempValue = env.status.ovenTempValue
        val info = WaresManager.selectInfo()

        if (MY_LOCATION == LOCATION_US) {
            val s = String.format(
                "%.1f℉->%.1f℉",
                tempValue * 1.8f + 32,
                info.wares.heatTempValue * 1.8f + 32
            )
            textView.text = s
        } else if (MY_LOCATION == LOCATION_UK) {
            val s = String.format("%d℃->%.1f℃", tempValue, info.wares.heatTempValue)
            textView.text = s
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onDeliveryChangedEvent(env: DeliveryChangedEvent) {
        when (env.state) {
            DeliveryChangedEvent.Take1 -> {

                take = DeliveryChangedEvent.Take1
                take1()
                textView.visibility = View.VISIBLE
                stepView.showWith4()
            }

            DeliveryChangedEvent.Take2 -> {

                take = DeliveryChangedEvent.Take2
                take2()
                textView.visibility = View.VISIBLE
                stepView.showWith3()
            }

            DeliveryChangedEvent.Take3 -> {

                take = DeliveryChangedEvent.Take3
                take3()
                textView.visibility = View.GONE
                stepView.showWith2()
            }

            DeliveryChangedEvent.Preheat -> {

                take1(DeliveryChangedEvent.Preheat)
                stepView.showWith4(1)
            }

            DeliveryChangedEvent.Heat -> {

                if (take == DeliveryChangedEvent.Take1) {
                    take1(DeliveryChangedEvent.Heat)
                    stepView.showWith4(2)
                } else {
                    take2(DeliveryChangedEvent.Heat)
                    stepView.showWith3(1)
                }
            }

            DeliveryChangedEvent.Deliver -> {

                if (take == DeliveryChangedEvent.Take1) {
                    take1(DeliveryChangedEvent.Deliver)
                    stepView.showWith4(3)
                } else if (take == DeliveryChangedEvent.Take2) {
                    take2(DeliveryChangedEvent.Deliver)
                    stepView.showWith3(2)
                } else {
                    take3(DeliveryChangedEvent.Deliver)
                    stepView.showWith2(1)
                }
            }

            DeliveryChangedEvent.Success -> {

                if (take == DeliveryChangedEvent.Take1) {
                    take1(DeliveryChangedEvent.Success)
                } else if (take == DeliveryChangedEvent.Take2) {
                    take2(DeliveryChangedEvent.Success)
                } else {
                    take3(DeliveryChangedEvent.Success)
                }

                onSuccess()
            }

            DeliveryChangedEvent.Error -> onError()

            DeliveryChangedEvent.Complete -> onComplete()

            /**
             * 其他错误信息， 如果已经出货成功则结束
             */
            else -> {
                if (DeliveryManager.isSuccess) {
                    onComplete()
                }
            }
        }
    }

    private fun dismiss() {
        if (!isShow) {
            return
        }
        isShow = false
        AppManager.isBusy = false

        EventBus.getDefault().unregister(this)
        deliveryView.progress.cancel()
        window.dismiss()
        closeTimer.cancel()
        deliveryTimer.cancel()
    }

    private fun onError() {
        log("出货失败", "出货")

        stepView.setTitle("Sorry, shipment failed!")
        DeliveryManager.isSuccess = false
        deliveryFlag = false
        PayManager.refund()

        deliveryTimer.cancel()
        closeTimer.start(2 * 1000L)

        if (cargo == null) {
            return
        }

        val info = WaresManager.selectInfo()
        val order = Order(
            info.wares.id,
            info.wares.name,
            info.wares.price,
            cargo!!.name,
            false
        )
        AsyncTask.post( OrderSaveTask(order) )
    }

    private fun onSuccess() {
        log("出货成功", "出货")

        if (DeliveryManager.isHot) {
            stepView.setTitle("Order ready.\r\nCAUTION : HOT FOOD")
        } else {
            stepView.setTitle("Order ready.")
        }

        DeliveryManager.isSuccess = true
        deliveryFlag = true
        PayManager.success()

        val info = WaresManager.selectInfo()
        val order = Order(
            info.wares.id,
            info.wares.name,
            info.wares.price,
            cargo!!.name,
            true
        )
        AsyncTask.post( OrderSaveTask(order) )
    }

    private fun onComplete() {
        log("出货完成", "出货")

        stepView.setTitle("Thank you. Enjoy !")
        deliveryTimer.cancel()
        closeTimer.start(2 * 1000L)
    }

    private fun onDeliveryTimeout() {
        log("出货超时")
        PostLogTask.send("出货超时")

        if (deliveryFlag == null) {
            onError()
            return
        }
        log("等待出货完成超时")
        dismiss()
    }

    fun show(view: View) {
        if (isShow) {
            return
        }
        isShow = true
        cargo = null
        AppManager.isBusy = true
        DeliveryManager.isSuccess = false
        deliveryFlag = null

        window.showAtLocation(view, Gravity.CENTER, 0, 0)
        EventBus.getDefault().register(this)
        initUi()
    }

    private fun initUi() {

        val info = WaresManager.selectInfo()
        textView.visibility = View.GONE
        iconImageView.setImageWithUrl(info.wares.maxImageUrl)
        deliveryView.progress.steps = emptyArray()
        stepView.setTitle("Please wait!")

        deliveryTimer.start(10 * 60 * 1000L)
        AsyncTask.post( DeliveryTask(info, DeliveryManager.isHot) )
    }
}
